package com.michale.admin.controller.permissions;

import com.github.pagehelper.PageInfo;
import com.michale.admin.controller.tool.BaseController;
import com.michale.common.annotation.Log;
import com.michale.common.constants.UserConstant;
import com.michale.common.domain.permissions.MenuEntity;
import com.michale.common.domain.permissions.RoleEntity;
import com.michale.common.domain.permissions.UserEntity;
import com.michale.common.domain.permissions.UserRoleEntity;
import com.michale.common.domain.security.LoginUserDetail;
import com.michale.common.domain.system.DeptEntity;
import com.michale.common.enmus.BusinessType;
import com.michale.common.result.AjaxResult;
import com.michale.common.result.PageResult;
import com.michale.common.utils.String.StringUtils;
import com.michale.common.utils.security.SecurityUtils;
import com.michale.framework.security.service.PermissionService;
import com.michale.framework.security.service.impl.TokenServiceImpl;
import com.michale.system.service.DeptService;
import com.michale.system.service.MenuService;
import com.michale.system.service.RoleService;
import com.michale.system.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;


/**
 * @author Michale
 * @apiNote 角色管理
 */
@Api(value = "角色管理")
@RestController
@RequestMapping("permissions/role")
public class RoleController extends BaseController {

    @Resource
    private RoleService roleService;
    @Resource
    private UserService userService;
    @Resource
    private DeptService deptService;
    @Resource
    private MenuService menuService;
    @Resource
    private TokenServiceImpl tokenUtils;
    @Resource
    private PermissionService permissionService;

    /**
     * 分页查询-角色信息列表
     *
     * @param roleEntity 分页查询参数
     * @return 角色信息列表
     */
    @GetMapping("/roleList")
    @ApiOperation(value = "分页查询", notes = "PageResult")
    @PreAuthorize("@security.isPermission('permissions:role:list')")
    public PageResult getRoleList(RoleEntity roleEntity) {
        startPage();
        List<RoleEntity> roleList = roleService.selectRoleList(roleEntity);
        PageInfo<RoleEntity> pageInfo = new PageInfo<>(roleList);
        return pageResult(pageInfo);
    }

    /**
     * 新增角色
     *
     * @param roleEntity 角色信息表信息
     * @return 结果
     */
    @PostMapping("/insertRole")
    @Log(title = "角色管理", businessType = BusinessType.INSERT)
    @PreAuthorize("@security.isPermission('permissions:role:add')")
    public AjaxResult insertRole(@Validated @RequestBody RoleEntity roleEntity) {

        if (UserConstant.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(roleEntity))) {
            return AjaxResult.error("新增角色'" + roleEntity.getRoleName() + "'失败，角色名称已存在");
        } else if (UserConstant.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(roleEntity))) {
            return AjaxResult.error("新增角色'" + roleEntity.getRoleName() + "'失败，角色权限已存在");
        }
        roleEntity.setCreateBy(SecurityUtils.getUsername());
        return toAjax(roleService.insertRole(roleEntity));
    }

    /**
     * 修改角色
     *
     * @param roleEntity 角色信息
     * @return 结果
     */
    @PutMapping("/updateRole")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PreAuthorize("@security.isPermission('permissions:role:edit')")
    public AjaxResult updateRole(@Validated @RequestBody RoleEntity roleEntity) {
        roleService.checkRoleAllowed(roleEntity);
        roleService.checkRoleDataScope(roleEntity.getRoleId());
        if (UserConstant.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(roleEntity))) {
            return AjaxResult.error("修改角色'" + roleEntity.getRoleName() + "'失败，角色名称已存在");
        } else if (UserConstant.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(roleEntity))) {
            return AjaxResult.error("修改角色'" + roleEntity.getRoleName() + "'失败，角色权限已存在");
        }
        roleEntity.setUpdateBy(getUsername());
        if (roleService.updateRole(roleEntity) > 0) {
            // 更新缓存用户权限
            LoginUserDetail loginUser = getLoginUser();
            if (StringUtils.isNotNull(loginUser.getUserEntity()) && !SecurityUtils.isAdmin(loginUser.getUserEntity().getIdentity())) {
                loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUserEntity()));
                loginUser.setUserEntity(userService.selectUserByUserName(loginUser.getUserEntity().getUserName()));
                tokenUtils.setLoginUser(loginUser);
            }
            return AjaxResult.success();
        }
        return AjaxResult.error("修改角色'" + roleEntity.getRoleName() + "'失败，请联系管理员");
    }

    /**
     * 修改角色状态
     *
     * @param roleEntity 修改状态参数
     * @return 结果
     */
    @PutMapping("/changeStatus")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PreAuthorize("@security.isPermission('permissions:role:edit')")
    public AjaxResult changeStatus(@RequestBody RoleEntity roleEntity) {
        roleService.checkRoleAllowed(roleEntity);
        roleService.checkRoleDataScope(roleEntity.getRoleId());
        return toAjax(roleService.updateRoleStatus(roleEntity));
    }

    /**
     * 根据角色ID获取详细信息
     *
     * @param roleId 角色ID
     * @return 结果
     */
    @GetMapping(value = "/{roleId}")
    @PreAuthorize("@security.isPermission('permissions:role:query')")
    public AjaxResult getInfo(@PathVariable Long roleId) {
        roleService.checkRoleAllowed(roleService.selectRoleById(roleId));
        roleService.checkRoleDataScope(roleId);
        return AjaxResult.success(roleService.selectRoleById(roleId));
    }

    /**
     * 根据角色ID删除角色信息
     *
     * @param roleIds 需要删除的角色ID
     * @return 结果
     */
    @DeleteMapping("/{roleIds}")
    @PreAuthorize("@security.isPermission('permissions:role:remove')")
    public AjaxResult deleteRole(@PathVariable Long[] roleIds) {
        for (Long roleId : roleIds) {
            roleService.checkRoleAllowed(roleService.selectRoleById(roleId));
        }
        return toAjax(roleService.deleteRoleByIds(roleIds));
    }

    /**
     * 根据角色ID查询已授权的用户列表
     *
     * @param sysUser 用户信息
     */
    @GetMapping("/allocatedList")
    public PageResult getAllocatedList(UserEntity sysUser) {
        roleService.checkRoleAllowed(roleService.selectRoleById(sysUser.getRoleId()));
        startPage();
        List<UserEntity> allocatedList = userService.selectAllocatedList(sysUser);
        PageInfo<UserEntity> pageInfo = new PageInfo<>(allocatedList);
        return pageResult(pageInfo);
    }

    /**
     * 查询未分配用户的角色列表
     *
     * @param sysUser 用户信息
     */
    @GetMapping("/unAllocatedList")
    public AjaxResult getUnAllocatedList(UserEntity sysUser) {
        List<UserEntity> unallocatedList = userService.selectUnAllocatedList(sysUser);
        return AjaxResult.success("查询未分配用户的角色列表", unallocatedList);
    }

    /**
     * 取消授权用户
     *
     * @param sysUserRoleEntity 角色和用户信息
     */
    @PutMapping("/cancelAuthUser")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PreAuthorize("@security.isPermission('permissions:role:edit')")
    public AjaxResult cancelAuthUser(@RequestBody UserRoleEntity sysUserRoleEntity) {
        roleService.checkRoleAllowed(roleService.selectRoleById(sysUserRoleEntity.getRoleId()));
        return toAjax(roleService.deleteAuthUser(sysUserRoleEntity));
    }

    /**
     * 批量权用户角色
     *
     * @param roleId  角色ID
     * @param userIds 需要取消授权的用户数据ID
     * @return 结果
     */
    @PutMapping("/selectAll")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PreAuthorize("@security.isPermission('permissions:role:edit')")
    public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) {
        roleService.checkRoleAllowed(roleService.selectRoleById(roleId));
        roleService.checkRoleDataScope(roleId);
        return toAjax(roleService.insertAuthUsers(roleId, userIds));
    }

    /**
     * 批量取消授权用户角色
     *
     * @param roleId  角色ID
     * @param userIds 需要取消授权的用户数据ID
     * @return 结果
     */
    @PutMapping("/cancelAll")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PreAuthorize("@security.isPermission('permissions:role:edit')")
    public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds) {
        roleService.checkRoleAllowed(roleService.selectRoleById(roleId));
        return toAjax(roleService.deleteAuthUsers(roleId, userIds));
    }

    /**
     * 授权数据权限
     *
     * @param roleEntity 角色信息
     */
    @PutMapping("/dataScope")
    @PreAuthorize("@security.isPermission('permissions:role:edit')")
    public AjaxResult dataScope(@RequestBody RoleEntity roleEntity) {
        roleService.checkRoleAllowed(roleEntity);
        roleService.checkRoleDataScope(roleEntity.getRoleId());
        return toAjax(roleService.authDataScope(roleEntity));
    }

    /**
     * 加载对应角色ID查询部门树列表
     *
     * @param roleId 角色ID
     */
    @GetMapping(value = "/roleDeptTreeSelect/{roleId}")
    @ApiOperation(value = "查询-加载对应角色菜单列表树", notes = "SysDept")
    public AjaxResult roleDeptTreeSelect(@PathVariable("roleId") Long roleId) {
        AjaxResult ajax = AjaxResult.success();
        ajax.put("deptIds", deptService.selectDeptListByRoleId(roleId));
        ajax.put("deptTree", deptService.selectDeptTreeList(new DeptEntity()));
        return ajax;
    }
    /**
     * 加载对应角色菜单列表树
     *
     * @param roleId 角色ID
     * @return 菜单列表树
     */
    @GetMapping("/roleMenuTreeSelect/{roleId}")
    @ApiOperation(value = "查询-加载对应角色菜单列表树", notes = "SysMenu")
    public AjaxResult roleMenuTreeSelect(@PathVariable("roleId") Long roleId) {
        AjaxResult ajax = AjaxResult.success();
        ajax.put("menuIds", menuService.selectMenuListByRoleId(roleId));
        ajax.put("menuTree", menuService.selectMenuTreeList(new MenuEntity()));
        return ajax;
    }
}
